<?php


namespace Trawind\Rocketmq\Jobs;


use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Trawind\Helpers\UserHelper;
use Trawind\Helpers\WechatHelper;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Trawind\Basics\Exceptions\LogicException;
use Trawind\ConfigCenter\Middleware\ConfigVersion;

abstract class TenancyRocketMqJob implements ShouldQueue
{

    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * tenant_id
     *
     * @var mixed|string|null
     */
    protected $tenantId;

    /**
     * Parameter carrier
     *
     * @var array
     */
    protected $payload;

    /**
     * The number of seconds the job can run before timing out.
     *
     * @var int
     */
    public $timeout = 180;

    /**
     * The number of times the job may be attempted.
     *
     * @var int
     */
    public $tries = 1;


    /**
     * @note 是否开启企业微信群的队列异常通知，可通过重写false关闭该继承job类的通知
     * 比如一些对接第三方平台的job，通常异常都是第三方抛出的无意义异常，不需要推送到机器人群通知就可以重写为false
     * @var bool
     */
    protected $exceptionNotification = true;


    public function __construct(array $payload)
    {
        $this->payload = $payload;
        $this->tenantId = UserHelper::tenantId();
        $this->connection = 'rocketmq';
        is_null($this->delay) and $this->delay(2);

        foreach ($this->payload as $property => $item) {
            property_exists(static::class, $property) and $this->$property = $item;
        }
    }


    public function getTenantId()
    {
        is_null($this->tenantId) and LogicException::error('The `tenantId` attribute of mq must be configured');
        return $this->tenantId;
    }


    final public function handle()
    {
        UserHelper::setConsoleTenantId($this->getTenantId());
        app()->has(ConfigVersion::USER_CONFIG) or app(ConfigVersion::class)->loadCommonConfig();

        $tenant = config('tenancy.tenant_model')::where('tenant_id', '=', $this->getTenantId())->firstOrFail();
        $tenant->run(function ($model) {
            $this->run();
        });
    }

    abstract public function run();


    public function failed(\Exception $e)
    {
        if ($this->exceptionNotification) {
            WechatHelper::factory()
                ->queueExceptionNotice(static::class, $e->getMessage())
                ->withDeveloper();
        }
    }

    /**
     * Determine the time at which the job should timeout.
     *
     * @return \DateTime
     */
    //    public function retryUntil()
    //    {
    //        return Carbon::now()->addMinutes(3);
    //    }
}